﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;




namespace Game.TDBehaviorTree
{ 

   [Serializable]
    public class NodeValue
    {
        //节点实体
        [System.NonSerialized] public NodeBase m_NodeBase;

        //节点实体参数
        public string[] m_NodeArgs=new string[5];

        //是否为跟节点
        public bool m_IsRoot = false;

        //组合节点类型
        public NodeType m_NodeType;

        //叶子节点类型
        public int m_LeafNodeType;

        //子节点序列号
        public int m_ChildIndex;

        //是否为组合节点
        public bool m_IsCombineNode = false;


        //子节点
        [NonSerialized]
        public List<NodeValue> m_ChildList = new List<NodeValue>();

        //子节点下标 用于恢复
        public List<int> m_m_ChildListIndex = new List<int>();
        public int m_FileIndex;   //处于编辑器文件下标

        public Rect m_Rect;
        
        public string m_Title;
        public bool m_IsDragged;
        public bool m_IsSelected;


        [System.NonSerialized]
        public TDConnectionPoint m_InPoint;
        [System.NonSerialized]
        public TDConnectionPoint m_OutPoint;

        private GUIStyle m_Style;
        private GUIStyle m_DefaultNodeStyle;
        private GUIStyle m_SelectedNodeStyle;


        private Action<NodeValue> OnRemoveNode;
        private Action<NodeValue> OnSetRootNode;

        [System.NonSerialized]
        public List<NodeValue> m_AllNodeValue;

        public NodeValue(int fileIndex,List<NodeValue>_AllNodeValue,NodeType _nodeType,ActionNodeType _actionNodeType,ConditionNodeType _conditionNodeType,DecorateNodeType _decorateNodeType, 
            Vector2 position, float width, float height, GUIStyle nodeStyle, GUIStyle selectedStyle, GUIStyle inPointStyle, GUIStyle outPointStyle, 
            Action<TDConnectionPoint> OnClickInPoint, Action<TDConnectionPoint> OnClickOutPoint, Action<NodeValue> OnClickRemoveNode,
            Action<NodeValue>OnClickSetRootNode)
        {

            m_FileIndex = fileIndex;
            m_AllNodeValue = _AllNodeValue;
            m_NodeType = _nodeType;

            if(m_NodeType==NodeType.Action || m_NodeType ==NodeType.Condition || m_NodeType == NodeType.Decorator)
            {
                m_IsCombineNode = false;
            }
            else 
            { 
                m_IsCombineNode = true;
            }


            if (m_NodeType == NodeType.Action)
                m_LeafNodeType = Convert.ToInt32(_actionNodeType);
            if(m_NodeType==NodeType.Condition)
                m_LeafNodeType = Convert.ToInt32(_conditionNodeType);
            if (m_NodeType == NodeType.Decorator)
                m_LeafNodeType = Convert.ToInt32(_decorateNodeType);


            m_Rect = new Rect(position.x, position.y, width, height);
            m_Style = nodeStyle;
            m_InPoint = new TDConnectionPoint(this, ConnectionPointType.In, inPointStyle, OnClickInPoint);
            m_OutPoint = new TDConnectionPoint(this, ConnectionPointType.Out, outPointStyle, OnClickOutPoint);
            m_DefaultNodeStyle = nodeStyle;
            m_SelectedNodeStyle = selectedStyle;
            OnRemoveNode = OnClickRemoveNode;
            OnSetRootNode = OnClickSetRootNode;
        }


        /// <summary>
        /// 反序列化初始化
        /// </summary>
        public void OnDeRealize(List<NodeValue>_AllNodeValue, GUIStyle nodeStyle, GUIStyle selectedStyle, GUIStyle inPointStyle, GUIStyle outPointStyle, Action<TDConnectionPoint> OnClickInPoint, Action<TDConnectionPoint> OnClickOutPoint, Action<NodeValue> OnClickRemoveNode, Action<NodeValue> OnClickSetRootNode)
        {
            m_Style = nodeStyle;
            m_InPoint = new TDConnectionPoint(this, ConnectionPointType.In, inPointStyle, OnClickInPoint);
            m_OutPoint = new TDConnectionPoint(this, ConnectionPointType.Out, outPointStyle, OnClickOutPoint);
            m_DefaultNodeStyle = nodeStyle;
            m_SelectedNodeStyle = selectedStyle;
            OnRemoveNode = OnClickRemoveNode;
            OnSetRootNode = OnClickSetRootNode;
            m_AllNodeValue = _AllNodeValue;
            if (m_NodeBase == null)
            {
                m_NodeBase = TDBehaviorBT.GetNode(m_NodeType, m_LeafNodeType);
                m_NodeBase.m_LeafType = m_LeafNodeType;
                m_ChildList = new List<NodeValue>();
                foreach (var item in m_m_ChildListIndex)
                {
                    m_ChildList.Add(m_AllNodeValue[item]);
                }
            }
        }

  

        public void Drag(Vector2 delta)
        {
            m_Rect.position += delta;
        }

        public void Draw()
        {
          
            GUI.Box(m_Rect, string.Empty, m_Style);

            GUILayout.BeginArea(new Rect(m_Rect.x + 10, m_Rect.y + 10, m_Rect.width, m_Rect.height));

            GUILayout.BeginVertical(GUILayout.Width(m_Rect.width), GUILayout.Height(m_Rect.height));

            if (m_NodeType == NodeType.Action)
            {
                GUILayout.Label("行为节点:");
                string[] actionTypes = EnumberHelper.EnumToArray<ActionNodeType>();
                NodeTypePopUpGuiAction(actionTypes);
            }
            else if (m_NodeType == NodeType.Condition)
            {
                GUILayout.Label("条件节点:");
                NodeTypePopUpGuiAction(EnumberHelper.EnumToArray<ConditionNodeType>());
            }
            else if (m_NodeType == NodeType.Decorator)
            {
                GUILayout.Label("装饰节点:");
                NodeTypePopUpGuiAction(EnumberHelper.EnumToArray<DecorateNodeType>());
            } 
            else
            {
                GUILayout.Label("节点:" + EnumberHelper.GetDescription(m_NodeType));
            }

            GUILayout.BeginHorizontal(GUILayout.Width(100), GUILayout.Height(20));
            GUILayout.Label("是否为跟节点:", GUILayout.Width(80), GUILayout.Height(20));
            m_IsRoot = EditorGUILayout.Toggle(m_IsRoot, GUILayout.Width(20), GUILayout.Height(20));
            if (m_IsRoot)
            {
                OnSetRootNode(this);
            }
            GUILayout.EndHorizontal();

            GUILayout.Label("描述:");
            m_Title = EditorGUILayout.TextField(m_Title, GUILayout.Width(120), GUILayout.Height(30));


            if (m_NodeBase == null)
            {
                m_NodeBase = TDBehaviorBT.GetNode(m_NodeType,m_LeafNodeType);
                m_NodeBase.m_LeafType = m_LeafNodeType;
            }


            GUILayout.BeginHorizontal(GUILayout.Width(100), GUILayout.Height(20));
          
            if (m_IsCombineNode)
            {
                GUILayout.Label("子节点个数:", GUILayout.Width(80), GUILayout.Height(20));
                EditorGUILayout.LabelField(m_ChildList.Count.ToString(), GUILayout.Width(20), GUILayout.Height(20));
            }

            GUILayout.EndHorizontal();

            if (m_IsCombineNode)
            {
                GUILayout.BeginVertical(GUILayout.Width(100));
                //显示出子节点排序后的UI
                for (int i = 0; i < m_ChildList.Count; i++)
                {
                    EditorGUILayout.LabelField(m_ChildList[i].m_ChildIndex+ ":"+ m_ChildList[i].m_NodeBase.GetNodeTypeDraw(), GUILayout.Height(20));
                }

                if (GUILayout.Button("更改子节点下标",GUILayout.Width(100), GUILayout.Height(20)))
                {
                    SortChildNode();
                }

                GUILayout.EndVertical();
            }



            if (!m_IsCombineNode)
            {
                float RectY = 0;
                if (!m_IsRoot)
                {
                    //不是主节点需要进行序列号处理进行排序
                    GUILayout.BeginHorizontal(GUILayout.Width(100),GUILayout.Height(20));
                    EditorGUILayout.LabelField("子节点下标",GUILayout.Width(60), GUILayout.Height(20));
                   
                    m_ChildIndex =Convert.ToInt32(EditorGUILayout.TextField(m_ChildIndex.ToString(), GUILayout.Width(40), GUILayout.Height(20)));
                    GUILayout.EndHorizontal();
                    RectY = m_Rect.y + 170;
                }
                else
                {
                    RectY= m_Rect.y + 150;
                }

                if (m_NodeBase != null)
                {
                   m_NodeBase.Draw(new Rect(m_Rect.x + 10, m_Rect.y + 170, m_Rect.width, 100), m_Style,this);
                }
            }
           

            GUILayout.EndVertical();


            GUILayout.EndArea();

            if (m_IsRoot)
            {
                m_OutPoint.Draw();
            }
            else
            {
                if (m_NodeType == NodeType.Action || m_NodeType == NodeType.Condition || m_NodeType == NodeType.Decorator)
                {
                    m_InPoint.Draw();
                }
                else
                {
                    m_InPoint.Draw();
                    m_OutPoint.Draw();
                }
            }
        }

        public bool ProcessEvents(Event e)
        {
            switch (e.type)
            {
                case EventType.MouseDown:
                    if (e.button == 0)
                    {
                        if (m_Rect.Contains(e.mousePosition))
                        {
                            m_IsDragged = true;
                            GUI.changed = true;
                            m_IsSelected = true;
                            m_Style = m_SelectedNodeStyle;
                        }
                        else
                        {
                            GUI.changed = true;
                            m_IsSelected = false;
                            m_Style = m_DefaultNodeStyle;
                        }
                    }

                    if (e.button == 1 && m_IsSelected && m_Rect.Contains(e.mousePosition))
                    {
                        ProcessContextMenu();
                        e.Use();
                    }
                    break;

                case EventType.MouseUp:
                    m_IsDragged = false;
                    break;

                case EventType.MouseDrag:
                    if (e.button == 0 && m_IsDragged)
                    {
                        Drag(e.delta);
                        e.Use();
                        return true;
                    }
                    break;
            }

            return false;
        }

        private void ProcessContextMenu()
        {
            GenericMenu genericMenu = new GenericMenu();
            genericMenu.AddItem(new GUIContent("Remove node"), false, OnClickRemoveNode);
            genericMenu.ShowAsContext();
        }

        private void OnClickRemoveNode()
        {
            if (OnRemoveNode != null)
            {
                OnRemoveNode(this);
                //m_NodeChildList.Clear();
                
            }
           
        }

        public void AddChildNode(NodeValue _node)
        {
            if (m_IsCombineNode)
            {
                _node.m_ChildIndex = m_ChildList.Count + 1;
                m_ChildList.Add(_node);
                m_m_ChildListIndex.Add(_node.m_FileIndex);
                (m_NodeBase as NodeCombine).AddNode(_node.m_NodeBase);
                SortChildNode();
            }
               
        }

        public void RemoveChildNode(NodeValue _node)
        {
            if (m_IsCombineNode)
            {
                (m_NodeBase as NodeCombine).m_childNodes.Remove(_node.m_NodeBase);
                m_ChildList.Remove(_node);
                m_m_ChildListIndex.Remove(_node.m_FileIndex);
                for (int i = 0; i < m_ChildList.Count; i++)
                {
                    m_ChildList[i].m_ChildIndex = i + 1;
                }

                SortChildNode();

            }
        }

        public bool SortChildNode()
        {
          
            if (m_IsCombineNode)
            {
                Dictionary<int, NodeValue> m_IndexHas = new Dictionary<int, NodeValue>();
                for (int i = 0; i < m_ChildList.Count; i++)
                {
                    if (!m_IndexHas.ContainsKey(m_ChildList[i].m_ChildIndex))
                    {
                        m_IndexHas.Add(m_ChildList[i].m_ChildIndex, m_ChildList[i]);
                    }
                    else
                    {
                        //重复ID进行警告
                        Debug.LogError("重复ID进行警告");
                        return true;
                    }
                }


                (m_NodeBase as NodeCombine).m_childNodes.Clear();
                m_ChildList.Sort((x, y) => x.m_ChildIndex.CompareTo(y.m_ChildIndex));

                for (int i = 0; i < m_ChildList.Count; i++)
                {
                    (m_NodeBase as NodeCombine).m_childNodes.Add(m_ChildList[i].m_NodeBase);
                }
                return false;
            }
            return false;
        }

        private void NodeTypePopUpGuiAction(string[] types)
        {
            int tempNodeType = m_LeafNodeType;
            m_LeafNodeType = EditorGUILayout.Popup(m_LeafNodeType, types, GUILayout.Width(130), GUILayout.Height(20));
            if (tempNodeType != m_LeafNodeType)
            {
                m_NodeBase = null;
            }
        }


      
    }


   
}
